package cn.bdqn.config;


import cn.bdqn.exception.AccessDeniedHandlerImpl;
import cn.bdqn.exception.AuthenticationEntryPointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Set;


@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)  //启用授权
public class SecurityConfig {

//    hasRole([role])	                 用户拥有制定的角色时返回true （Spring security默认会带有ROLE_前缀）
//    hasAnyRole([role1,role2])	       用户拥有任意一个制定的角色时返回true
//    hasAuthority([authority])	       等同于hasRole,但不会带有ROLE_前缀
//    asAnyAuthority([auth1,auth2])     等同于hasAnyRole
//    permitAll	                       永远返回true
//    denyAll	                         永远返回false
//    authentication	                当前登录用户的authentication对象
//    fullAuthenticated	                当前用户既不是anonymous也不是rememberMe用户时返回true
//    hasIpAddress(‘192.168.1.0/24’))	请求发送的IP匹配时返回true



    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Autowired
    private AuthenticationEntryPointImpl authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;

    /**
     * 获取AuthenticationManager（认证管理器），登录时认证使用
     * @param authenticationConfiguration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }


    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                // 基于 token，不需要 csrf
                .csrf().disable()
                // 基于 token，不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                //用于登录接口,允许匿名访问
                .antMatchers("/api/admin/login","http://localhost:8088/","/api/verification").permitAll() // 登录或者没登录都可以访问

                .antMatchers("/api/login","/login").anonymous() //匿名访问 一旦登录  不能再访问

                //除上面以外请求都需要权限认证
                .anyRequest().authenticated()
                //添加token过滤器
                .and().addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
                //认证失败处理器
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
                //授权失败处理器
                .accessDeniedHandler(accessDeniedHandler)
                .and().build();

    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}
